﻿using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace HMediatR
{
    public class BaseContext: DbContext
    {
        public BaseContext()
        {

        }
        private readonly IMediator mediator;
        public BaseContext(IMediator mediator)
        {
            this.mediator = mediator;
        }
        /// <summary>
        /// 重载 SaveChangesAsync  在上下文保存时 发布消息
        /// </summary>
        /// <param name="acceptAllChangesOnSuccess"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
        {
            var domainEnties = this.ChangeTracker.Entries<BaseEntity>().Where(x => x.Entity.GetAllEvents().Any());//找出所有继承自BaseEntity 并且包含未发布事件的对象
            var domainEvents = domainEnties.SelectMany(x => x.Entity.GetAllEvents()).ToList();//查找所有注册的事件
            var result =await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); //保存数据库
            domainEvents.ForEach(async x => await mediator.Publish(x, cancellationToken));//发送消息
            domainEnties.ToList().ForEach(x => x.Entity.RemoveEvent());//清空消息
            return result;
        }

        /// <summary>
        /// 重载 SaveChanges  在上下文保存时 发布消息
        /// </summary>
        /// <param name="acceptAllChangesOnSuccess"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override int SaveChanges()
        {
            var domainEnties = this.ChangeTracker.Entries<BaseEntity>().Where(x => x.Entity.GetAllEvents().Any());//找出所有继承自BaseEntity 并且包含未发布事件的对象
            var domainEvents = domainEnties.SelectMany(x => x.Entity.GetAllEvents()).ToList();//查找所有注册的事件
            var result = base.SaveChanges(); //保存数据库
            domainEvents.ForEach(async x => await mediator.Publish(x));//发送消息
            domainEnties.ToList().ForEach(x => x.Entity.RemoveEvent());//清空消息
            return result;
        }
    }
}
